package tests;

import static org.junit.Assert.*;

import java.util.LinkedList;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import category.Category;
import category.CategoryCollection;
import database.Repository;

public class DatabaseCategoryTest 
{
	private static Category category1 = null;
    private static Category category1_1 = null;
    private static Category category1_2 = null;
    private static Category category1_1_1 = null;
    private static Category category2 = null;
    private static Category category2_1 = null;
    private static Category category2_2 = null;
    private static Category category2_1_1 = null;
    private static Category category2_1_2 = null;
    private static Category category2_1_3 = null;
    private static Category category3 = null;
    private static Category category3_1 = null;
    private static Category category3_2 = null;
    private static Category categoryx = null;
    private static Category categoryy = null;
    
    @BeforeClass
	public static void setUp() 
	{
      category1 = new Category("category1");
      category1_1 = new Category("category1_1");
      category1_1.setFather(category1);
      category1_2 = new Category("category1_2");
      category1_2.setFather(category1);
      category1_1_1 = new Category("category1_1_1");
      category1_1_1.setFather(category1_1);
      
      category2 = new Category("category2");
      category2_1 = new Category("category2_1");
      category2_1.setFather(category2);
      category2_2 = new Category("category2_2");
      category2_2.setFather(category2);
      category2_1_1 = new Category("category2_1_1");
      category2_1_1.setFather(category2_1);
      category2_1_2 = new Category("category2_1_2");
      category2_1_2.setFather(category2_1);
      category2_1_3 = new Category("category2_1_3");
      category2_1_3.setFather(category2_1);
      
      category3 = new Category("category3");
      category3_1 = new Category("category3_1");
      category3_1.setFather(category3);
      category3_2 = new Category("category3_2");
      category3_2.setFather(category3);
      
      LinkedList<Category> subcategoriesOfX = new LinkedList<Category>();
      subcategoriesOfX.add(category1_1);
      subcategoriesOfX.add(category1_2);
      categoryx = new Category("categoryx");
      categoryx.setFather(category1);
      categoryx.setSubCategories(subcategoriesOfX);
      
      LinkedList<Category> subcategoriesOfY = new LinkedList<Category>();
      subcategoriesOfY.add(category1);
      categoryy = new Category("categoryy");
      categoryy.setSubCategories(subcategoriesOfY);
   }
    
    @Test
	public void insertCategory1AtLevel1() 
	{
      assertTrue(Repository.insertCategory(category1));
      assertTrue(Repository.existsCategory(category1.getName()));
    }
    
    @Test
   	public void insertCategory1_1AtLevel2() 
   	{
      assertTrue(Repository.insertCategory(category1_1));
      assertTrue(Repository.existsCategory(category1_1.getName()));
    }
    
    @Test
   	public void insertCategory1_2AtLevel2() 
   	{
      assertTrue(Repository.insertCategory(category1_2));
      assertTrue(Repository.existsCategory(category1_2.getName()));
   	}
    
    @Test
   	public void insertCategory1_1_1AtLevel3() 
   	{
      assertTrue(Repository.insertCategory(category1_1_1));
      assertTrue(Repository.existsCategory(category1_1_1.getName()));
      
   	}
    
    @Test
	public void insertCategory2() 
	{
      assertTrue(Repository.insertCategory(category2));
      assertTrue(Repository.insertCategory(category2_1));
      assertTrue(Repository.insertCategory(category2_2));
      assertTrue(Repository.insertCategory(category2_1_1));
      assertTrue(Repository.insertCategory(category2_1_2));
      assertTrue(Repository.insertCategory(category2_1_3));
    }
    
    @Test
   	public void loadCategories() 
   	{
      CategoryCollection categories = Repository.loadCategories();
      Category cat1 = categories.getCategoryList().get("category1");
      Category cat2 = categories.getCategoryList().get("category2");
      
      assertTrue(cat1.getName().equals("category1"));
      assertTrue(cat1.getSubCategories().get(0).getName().equals("category1_1"));
      assertTrue(cat1.getSubCategories().get(1).getName().equals("category1_2"));
      assertTrue(cat1.getSubCategories().get(0).getSubCategories().get(0).getName().equals("category1_1_1"));
      
      assertTrue(cat2.getName().equals("category2"));
      assertTrue(cat2.getSubCategories().get(0).getName().equals("category2_1"));
      assertTrue(cat2.getSubCategories().get(1).getName().equals("category2_2"));
      assertTrue(cat2.getSubCategories().get(0).getSubCategories().get(0).getName().equals("category2_1_1"));
      assertTrue(cat2.getSubCategories().get(0).getSubCategories().get(1).getName().equals("category2_1_2"));
      assertTrue(cat2.getSubCategories().get(0).getSubCategories().get(2).getName().equals("category2_1_3"));
   	
   	}
    
    @Test
   	public void insertCategoriesAndUpdate() 
   	{
      CategoryCollection categories = Repository.loadCategories();	
      
      assertTrue(!Repository.existsCategory("category3"));
      categories = Repository.insertCategoryAndUpdate(category3);
      assertTrue(Repository.existsCategory("category3"));
      
      categories = Repository.insertCategoryAndUpdate(category3_1);
      categories = Repository.insertCategoryAndUpdate(category3_2);
      
      Category cat3 = categories.getCategoryList().get("category3");
      assertTrue(cat3.getName().equals("category3"));
      assertTrue(cat3.getSubCategories().get(0).getName().equals("category3_1"));
      assertTrue(cat3.getSubCategories().get(1).getName().equals("category3_2"));
   	}
    
    @Test
  	public void insertCategoryXAsNewFatherOfCategory1_1AndCategory1_2() 
  	{
      assertTrue(Repository.insertCategory(categoryx));
      
      CategoryCollection categories = Repository.loadCategories();
      Category cat1 = categories.getCategoryList().get("category1");
      
      assertTrue(cat1.getName().equals("category1"));
      assertTrue(cat1.getSubCategories().get(0).getName().equals("categoryx"));
      assertTrue(cat1.getSubCategories().get(0).getSubCategories().get(0).getName().equals("category1_1"));
      assertTrue(cat1.getSubCategories().get(0).getSubCategories().get(1).getName().equals("category1_2"));
      assertTrue(cat1.getSubCategories().get(0).getSubCategories().get(0).getSubCategories().get(0).getName().equals("category1_1_1"));
  	
      Category catx = categories.getCategoryList().get("categoryx");
      assertTrue(catx.getFather().getName().equals("category1"));
      assertTrue(catx.getSubCategories().get(0).getName().equals("category1_1"));
      assertTrue(catx.getSubCategories().get(1).getName().equals("category1_2"));
  	}
    
    @Test
  	public void insertCategoryYAsNewFatherOfCategory1() 
  	{
      assertTrue(Repository.insertCategory(categoryy));
        
      CategoryCollection categories = Repository.loadCategories();
      Category cat1 = categories.getCategoryList().get("category1");
      
      assertTrue(cat1.getFather().getName().equals("categoryy"));
      assertTrue(cat1.getFather().getFather() == null);
      assertTrue(cat1.getSubCategories().get(0).getName().equals("categoryx"));
  	}
    
    @Test
  	public void insertCategory1AtOnceWithOneMethodCall() 
  	{
      Repository.deleteCategory(category1);
      Repository.deleteCategory(category1_1);
      Repository.deleteCategory(category1_2);
      Repository.deleteCategory(category1_1_1);
      Repository.deleteCategory(categoryx);
      Repository.deleteCategory(categoryy);
      
      LinkedList<Category> categoriesOfCategory1 = new LinkedList<Category>();
      categoriesOfCategory1.add(category1);
      categoriesOfCategory1.add(category1_1);
      categoriesOfCategory1.add(category1_2);
      categoriesOfCategory1.add(category1_1_1);
      
      assertTrue(Repository.insertCategories(categoriesOfCategory1));
      loadCategories();
  	}
    
    @AfterClass
	public static void cleanUp() 
	{
      Repository.deleteCategory(category1);
      Repository.deleteCategory(category1_1);
      Repository.deleteCategory(category1_2);
      Repository.deleteCategory(category1_1_1);
      Repository.deleteCategory(category2);
      Repository.deleteCategory(category2_1);
      Repository.deleteCategory(category2_2);
      Repository.deleteCategory(category2_1_1);
      Repository.deleteCategory(category2_1_2);
      Repository.deleteCategory(category2_1_3);
      Repository.deleteCategory(category3);
      Repository.deleteCategory(category3_1);
      Repository.deleteCategory(category3_2);
      Repository.deleteCategory(categoryx);
      Repository.deleteCategory(categoryy);
    }

}

